#!/bin/bash
###################################################
###
### tfs new -dir "your local folder path" -server "server-url" -src "path on tfs server" -login "username@domain,password"
### tfs update
### tfs revert -version 100231
### tfs remove local
###
### Author Jacky Qiu
###
### Email qunxyz@gmail.com
###
###################################################
DIRECTORY_PATH=~/.tfs
GLOBAL_CONF="$DIRECTORY_PATH/global.conf"
TF_PATH=$(cd "$(dirname "$0")"; pwd)
TMP_FILE_PATH=`date '+%s'`
TMP_LOCAL_FILE_PATH="local_files_$TMP_FILE_PATH"
TMP_TFS_FILE_PATH="tfs_files_$TMP_FILE_PATH"

UPDATE_CONTENT=""

GLOBAL_COLLECTION=""
GLOBAL_AUTH=""

COLLECTION=""
AUTH=""

pathname=`ls -l $TF_PATH/tfs |cut -d'>' -f2|awk '{print $1}'|sed -e 's/\/tfs//'`
if [ -d "$pathname" ]; then
    TF_PATH="$pathname"
fi
TF_PATH="$TF_PATH/"
CURRENT_PATH=${PWD}
DIR_NAME=${PWD##*/}

usage(){
    echo "Usage: $0 [n|new -dir dir-name -server tfs-url -src tfs-path -login tfs-login] [up|update [-version=version-number] [-overwrite] [-file file-path] [-force]] [re|revert -version=version-number [-file file-path]] [rs|reset -src=new-src] [rm|remove dir-name]"
    echo "       new : Create new tfs workplace"
    echo "       update : Update workplace"
    echo "       revert : Revert workplace"
    echo "       reset : Reset workplace"
    echo "       remove : Remove workplace(Need to cd to parent folder)"
    exit -1
}

#set workspace name
set_workspace_name(){
    time=`date '+%s'`
	WORKSPACE="${time}_${DIR_NAME}"
}

#write global conf
write_global_conf(){
	echo -e "COLLECTION=\"$COLLECTION\"">>"$GLOBAL_CONF"
	echo -e "AUTH=\"$AUTH\"">>"$GLOBAL_CONF"
}

#write conf
write_conf(){
	echo -e "LOCAL_PATH=\"$CURRENT_PATH\"">>"$CONF_FILE"
	echo -e "DIR_NAME=\"$DIR_NAME\"">>"$CONF_FILE"
	echo -e "WORKSPACE=\"$WORKSPACE\"">>"$CONF_FILE"
	echo -e "SRC_PATH=\"$SRC_PATH\"">>"$CONF_FILE"
}

#create a new workspace
create_workspace(){
	"$TF_PATH"tf workspace -server:"$COLLECTION" -new "$WORKSPACE" -login:"$AUTH"
}

#map workspace
map_workspace(){
	"$TF_PATH"tf workfold -server:"$COLLECTION" -workspace:"$WORKSPACE" -map "$SRC_PATH" "$LOCAL_PATH" -login:"$AUTH"
}

#unmap workspace
unmap_workspace(){
	"$TF_PATH"tf workfold -server:"$COLLECTION" -workspace:"$WORKSPACE" -unmap "$SRC_PATH" -login:"$AUTH"
}

#delete workspace
delete_workspace(){
	"$TF_PATH"tf workspace -delete "$WORKSPACE" -login:"$AUTH" -collection:"$COLLECTION"
}

#get files
get_files(){
	"$TF_PATH"tf get "$CURRENT_PATH_RELATIVE"  -recursive -login:"$AUTH" $QUERY_VERSION $FILE_STR $OVER_WRITE_STR $FORCE_STR
	#echo "${TF_PATH}tf get $CURRENT_PATH_RELATIVE -recursive -login:$AUTH $QUERY_VERSION $FILE_STR $OVER_WRITE_STR $FORCE_STR"
}

#get file list on tfs server
get_tfs_file_list(){
	"$TF_PATH"tf dir -recursive -login:"$AUTH" "$SRC_PATH" $QUERY_VERSION>>$TMP_FILE_PATH
	
	line_number=0
	file_count=0
	line_count=`sed -n '$=' $TMP_FILE_PATH`
	tmp_path=""
	tmp_base_path=""

	while read LINE
	do
		if [ "$LINE" ]; then
			if [ ${LINE:0:1} = "\$" ]; then
				if [ $line_number = 0 ]; then
					tmp_base_path=`echo ${LINE%:*}`
					tmp_path="$tmp_base_path"
				else
					if [ ${LINE:0:2} = "\$/" ]; then
						tmp_path=`echo ${LINE%:*}`
					fi
				fi
				#if [ ${LINE:0:2} != "\$/" ]; then
				#	tmp_path=`echo ${tmp_path##*$}`
				#	tmp_path="$tmp_base_path/$tmp_path"
				#fi
			else
				if [ $line_number -lt $(($line_count - 1)) ]; then
					LINE=`echo ${LINE##*$}`
					file="$tmp_path/$LINE"
					file=`echo ${file##*$tmp_base_path}`
					tfs_file_list[$file_count]="$file"
					echo "$file">>$TMP_TFS_FILE_PATH
					file_count=$(($file_count + 1))
				fi
			fi
		fi
		line_number=$(($line_number + 1))
	done < $TMP_FILE_PATH
}

#get local dir list
get_local_dir_list(){
	file_count=0
	for file_item in $(find $LOCAL_PATH -type d); do
		file=`echo ${file_item##*$LOCAL_PATH}`
		local_dir_list[$file_count]="$file"
		file_count=$(($file_count + 1))
	done
}

#get local file list
get_local_file_list(){
	file_count=0
	echo "find $LOCAL_PATH -type f $skip_dir_str"
	for file_item in $(find $LOCAL_PATH -type f $skip_dir_str); do
		file=`echo ${file_item##*$LOCAL_PATH}`
		local_file_list[$file_count]="$file"
		echo "$file">>$TMP_LOCAL_FILE_PATH
		file_count=$(($file_count + 1))
	done
}

#process file list content
process_file_list(){
	tfs_file_list=()
	local_file_list=()
	local_dir_list=()
	skip_dir_str=""

	get_tfs_file_list
	get_local_dir_list
	local_dir_list_len=`echo ${#local_dir_list[@]}`
	line_number=0

	for (( i=0; i<"$local_dir_list_len"; i=i+1 )); do
		local_dir_item=${local_dir_list[$i]}
		
		in_flag=0
		#echo "cat $TMP_TFS_FILE_PATH|grep -c ^$local_dir_item"
		if [ "`cat $TMP_TFS_FILE_PATH|grep -c ^$local_dir_item`" != 0 ]; then
			in_flag=1
		fi
		if [ "$in_flag" != 1 ]; then
			skip_dir_str="-o \( ! -name \"$local_dir_item\" \) $skip_dir_str"
		fi
	done
	
	get_local_file_list
#	"$TF_PATH"tf dir -recursive -login:"$AUTH" "$SRC_PATH" $QUERY_VERSION>>$TMP_FILE_PATH
#	
#	line_number=0
#	file_count=0
#	line_count=`sed -n '$=' $TMP_FILE_PATH`
#	tmp_path=""
#	tmp_base_path=""
#
#	while read LINE
#	do
#		if [ "$LINE" ]; then
#			if [ ${LINE:0:1} = "\$" ]; then
#				if [ $line_number = 0 ]; then
#					tmp_base_path=`echo ${LINE%:*}`
#					tmp_path="$tmp_base_path"
#				else
#					if [ ${LINE:0:2} = "\$/" ]; then
#						tmp_path=`echo ${LINE%:*}`
#					fi
#				fi
#			else
#				if [ $line_number -lt $(($line_count - 1)) ]; then
#					LINE=`echo ${LINE##*$}`
#					file="$tmp_path/$LINE"
#					file=`echo ${file##*$tmp_base_path}`
#					#tfs_file_list[$file_count]="$file"
#					#echo "$file">>$TMP_TFS_FILE_PATH
#
#					in_flag=0
#
#					if [ "`cat $TMP_LOCAL_FILE_PATH|grep -c ^$file$`" != 0 ]; then
#						in_flag=1
#					fi
#
#					if [ $in_flag != 1 ]; then
#						#echo "update item: $file"
#						CURRENT_PATH_RELATIVE="${SRC_PATH}${file}"
#						FORCE_STR=" -force"
#						OVER_WRITE_STR=" -overwrite"
#						get_files
#						#update_file_list[$update_file_count]="$file"
#						#update_file_count=$(($update_file_count + 1))
#					#else
#						#echo "keeped item: $file"
#					fi
#				fi
#			fi
#		fi
#		line_number=$(($line_number + 1))
#	done < $TMP_FILE_PATH
#	rm $TMP_FILE_PATH
#	rm $TMP_LOCAL_FILE_PATH

#	while read tfs_item
#	do
#		in_flag=0
#		while read local_item
#		do
#			if [ "$local_item" = "$tfs_item" ]; then
#				in_flag=1
#			fi
#		done < $TMP_LOCAL_FILE_PATH
#		if [ $in_flag != 1 ]; then
#			echo "update item: $tfs_item"
#			update_file_list[$update_file_count]="$tfs_item"
#			update_file_count=$(($update_file_count + 1))
#		#else
#			#echo "keeped item: $tfs_item"
#		fi
#		line_number=$(($line_number + 1))
#	done < $TMP_TFS_FILE_PATH
#	#rm $TMP_TFS_FILE_PATH
#	#rm $TMP_LOCAL_FILE_PATH

	tfs_len=`echo ${#tfs_file_list[@]}`
	local_len=`echo ${#local_file_list[@]}`
	
	for (( j=0; j<"$tfs_len"; j=j+1 )); do
		tfs_item=${tfs_file_list[$j]}
		in_flag=0
		for (( i=0; i<"$local_len"; i=i+1 )); do
			local_item=${local_file_list[$i]}
			
			if [ "$local_item" = "$tfs_item" ]; then
				#echo "$local_item = $tfs_item"
				in_flag=1
				break
			fi
		done
		if [ $in_flag != 1 ]; then
			#echo "update item: $tfs_item"
			update_file_list[$update_file_count]="$tfs_item"
			update_file_count=$(($update_file_count + 1))
		#else
			#echo "keeped item: $tfs_item"
		fi
	done
}

version(){
	echo "tfs version 1.0"
	exit -1
}

if [ ! -d "$DIRECTORY_PATH" ]; then
	mkdir $DIRECTORY_PATH
fi

if [ -f "$GLOBAL_CONF" ]; then
	source "$GLOBAL_CONF"
fi

if [ "$GLOBAL_COLLECTION" ]; then
	COLLECTION="$GLOBAL_COLLECTION"
fi

if [ "$GLOBAL_AUTH" ]; then
	AUTH="$GLOBAL_AUTH"
fi

while [ $# -gt 0 ]; do
	case $1 in
		n|new)
			DIR_NAME=""
			QUERY_VERSION=""
			USER_NAME=""
			DOMAIN=""
			PASSWORD=""
			CURRENT_PATH=""
			CONF_FILE=""
			VAR=""
			CURRENT_PATH=""
			WORKSPACE=""
			SRC_PATH=""
			CONF_NAME=""

			for arg in "$@"
			do
				case $VAR in
					-dir)
						DIR_NAME=$arg
					;;
					-server)
						COLLECTION=$arg
					;;
					-src)
						SRC_PATH=$arg
					;;
					-login)
						AUTH=$arg
					;;
					-version)
						QUERY_VERSION=" -version:$arg -all -overwrite"
					;;
				esac
				VAR=$arg
			done

			while [ ! "$DIR_NAME" ]
			do
				echo -n "Please enter a directory name:"
				echo ""
				read DIR_NAME
			done

			while [ ! "$COLLECTION" ]
			do
				echo -n "Please enter tfs server url(like http://prdtfs01:8080/tfs/defaultcollection):"
				echo ""
				read COLLECTION
			done

			while [ ! "$SRC_PATH" ]
			do
				echo -n "Please enter tfs source path(like $/The Knot China/Trunk/Local):"
				echo ""
				read SRC_PATH
			done

			while [ ! "$AUTH" ]
			do
				while [ ! "$USER_NAME" ]
				do
					echo -n "Please enter your username:"
					echo ""
					read USER_NAME
				done
				while [ ! "$DOMAIN" ]
				do
					echo -n "Please enter domain:"
					echo ""
					read DOMAIN
				done
				while [ ! "$PASSWORD" ]
				do
					echo -n "Please enter your password:"
					echo ""
					oldtty=`stty -g`
					stty -echo
					read PASSWORD
					stty $oldtty 
				done
				echo "Enter complete, Please wait...."

				AUTH="$USER_NAME@$DOMAIN,$PASSWORD"
			done
			
			CURRENT_PATH="${PWD}/$DIR_NAME"
			CONF_NAME=${CURRENT_PATH//\//\_}
			CONF_FILE="$DIRECTORY_PATH/$CONF_NAME.conf"
			set_workspace_name

			LOCAL_PATH="$CURRENT_PATH"
			if [ ! -f "$CONF_FILE" ]; then
				write_conf
			fi

			if [ ! -f "$GLOBAL_CONF" ]; then
				write_global_conf
			fi

			create_workspace
			if [ ! -d "$LOCAL_PATH" ]; then
				mkdir "$LOCAL_PATH"
			fi

			map_workspace

			cd "$LOCAL_PATH"
			get_files
			exit 0
			;;
		up|update)
			FORCE_STR=""
			VAR=""
			QUERY_VERSION=""
			OVER_WRITE_STR=""
			CHECK_STR=""
			FILE_STR=""
			CURRENT_PATH="${PWD}"
			CONF_NAME=${CURRENT_PATH//\//\_}
			CONF_FILE="$DIRECTORY_PATH/$CONF_NAME.conf"
			while [ ! -f "$CONF_FILE" ]; do
				CURRENT_PATH=`dirname $CURRENT_PATH`
				if [ $CURRENT_PATH = "/" ]; then
					echo "No source control in this path!"
					exit -1
				fi
				CONF_NAME=${CURRENT_PATH//\//\_}
				CONF_FILE="$DIRECTORY_PATH/$CONF_NAME.conf"
			done
			if [ -f "$CONF_FILE" ]; then
				source "$CONF_FILE"
			fi
			CURRENT_PATH_RELATIVE=${PWD//LOCAL_PATH/}

			for arg in "$@"
			do
				case $VAR in
					-file)
						FILE_STR="$arg"
					;;
					-version)
						QUERY_VERSION=" -version:$arg"
					;;
				esac
				VAR=$arg
				if [ "$VAR" = "-force" ]; then
					FORCE_STR=" -force"
				fi
				if [ "$VAR" = "-overwrite" ]; then
					OVER_WRITE_STR=" -overwrite"
				fi
				if [ "$VAR" = "-check" ]; then
					CHECK_STR="-check"
				fi
			done

#			if [ "$FORCE_STR" ]; then
#				unmap_workspace
#				delete_workspace
#				set_workspace_name
#				create_workspace
#				map_workspace
#				write_conf
#			fi

			get_files

			#if [ "$CHECK_STR" ]; then
				#update_file_list=()
				#update_file_count=0
				#echo "Checking missed files, Please wait for a moment..."
				#process_file_list

				#update_file_content=""
				#update_list_len=`echo ${#update_file_list[@]}`
				#for (( i=0; i<"$update_list_len"; i=i+1 )); do
				#	update_item=${update_file_list[$i]}
					
				#	CURRENT_PATH_RELATIVE="${SRC_PATH}${update_item}"
				#	FORCE_STR=" -force"
				#	OVER_WRITE_STR=" -overwrite"
				#	get_files
					#update_file_content="${update_file_content}${UPDATE_CONTENT}"
				#done
			#fi
			echo "Updated successfully!"
			
			exit 0
			;;
		re|revert)
			FORCE_STR=""
			QUERY_VERSION=""
			FILE_STR=""
			CURRENT_PATH="${PWD}"
			CONF_NAME=${CURRENT_PATH//\//\_}
			CONF_FILE="$DIRECTORY_PATH/$CONF_NAME.conf"
			if [ -f "$CONF_FILE" ]; then
				source "$CONF_FILE"
			else
				echo "No source control in this path!"
				exit -1
			fi

			for arg in "$@"
			do
				case $VAR in
					-file)
						FILE_STR="$arg"
					;;
					-version)
						QUERY_VERSION=" -version:$arg"
					;;
				esac
				VAR=$arg

				if [ "$VAR" == "-force" ]; then
						FORCE_STR=" -force"
				fi
			done
			
			while [ ! "$QUERY_VERSION" ]
			do
				echo -n "You must enter a version number:"
				echo ""
				read USER_VERSION
				if [ "$USER_VERSION" ]; then
					QUERY_VERSION=" -version:$USER_VERSION"
				fi
			done

			unmap_workspace
			LOCAL_PATH="$CURRENT_PATH"
			map_workspace
			get_files
			exit 0
			;;
		rs|reset)
			FORCE_STR=""
			QUERY_VERSION=""
			FILE_STR=""
			NEW_SRC_PATH=""
			CURRENT_PATH="${PWD}"
			CONF_NAME=${CURRENT_PATH//\//\_}
			CONF_FILE="$DIRECTORY_PATH/$CONF_NAME.conf"
			if [ -f "$CONF_FILE" ]; then
				source "$CONF_FILE"
			else
				echo "No source control in this path!"
				exit -1
			fi

			for arg in "$@"
			do
				VAR=$arg

				case $VAR in
					-src)
						NEW_SRC_PATH="$arg"
					;;
					-version)
						QUERY_VERSION=" -version:$arg"
					;;
					-force)
						FORCE_STR=" -force"
					;;
				esac
			done
			
			while [ ! "$NEW_SRC_PATH" ]
			do
				echo -n "You must enter src path(like $/The Knot China/Trunk/Local):"
				echo ""
				read NEW_SRC_PATH
			done

			unmap_workspace
			SRC_PATH="$NEW_SRC_PATH"
			LOCAL_PATH="$CURRENT_PATH"
			map_workspace
			write_conf

			get_files

			exit 0
			;;
		p|publish)
			QUERY_VERSION=""
			USER_VERSION=""
			CURRENT_PATH="${PWD}"
			CONF_NAME=${CURRENT_PATH//\//\_}
			CONF_FILE="$DIRECTORY_PATH/$CONF_NAME.conf"
			if [ -f "$CONF_FILE" ]; then
				source "$CONF_FILE"
			else
				echo "No source control in this path!"
				exit -1
			fi

			for arg in "$@"
			do
				VAR=$arg

				case $VAR in
					-src)
						PUBLISH_SRC="$arg"
					;;
					-version)
						QUERY_VERSION=" -version:$arg"
					;;
					-force)
						FORCE_STR=" -force"
					;;
				esac
			done

			while [ ! "$QUERY_VERSION" ]
			do
				echo -n "You must enter a version number:"
				echo ""
				read USER_VERSION
				if [ "$USER_VERSION" ]; then
					QUERY_VERSION=" -version:$USER_VERSION"
				fi
			done
			
			if [ "$PUBLISH_SRC" ]; then
				unmap_workspace
				SRC_PATH="$PUBLISH_SRC"
				map_workspace
				write_conf
			fi

			get_files
			exit 0
			;;
		rm|remove)
			DIR_NAME=$2
			CURRENT_PATH="${PWD}/$DIR_NAME"
			CONF_NAME=${CURRENT_PATH//\//\_}
			CONF_FILE="$DIRECTORY_PATH/$CONF_NAME.conf"
			if [ -f "$CONF_FILE" ]; then
				source "$CONF_FILE"
			else
				echo "No source control in this $DIR_NAME!"
				exit -1
			fi
			
			delete_workspace
			rm -rf "$DIR_NAME"
			rm -rf "$CONF_FILE"
			exit 0
			;;
		v|version)
			version
			exit 0
			;;
		h|help)
			usage
			exit 0
			;;
		*)
			usage
			exit 1
			;;
	esac
done

usage
exit 1